# encoding: utf-8
"""
@author: pywcc
@contact: 2371273856@qq.com
@software: PyCharm
@file: gui_handler.py
"""
import math
import os
import time
import tkinter as tk
from decimal import Decimal, ROUND_HALF_UP
from tkinter import messagebox
from tkinter.filedialog import askdirectory

import win32con
import win32gui as win32gui
import win32print
import yaml
from PIL import ImageGrab, Image
from win32api import GetSystemMetrics

# 常量
NAME = u"ScreenShotTool"
VERSION = u'v1.0.0.3'
GIT_PATH = u"https://gitee.com/pywcc/screen_shot_tool.git"
EDITOR = u'pywcc'
EMAIL = u"2371273856@qq.com"
HELP_MSG = u"""
{}
    源代码：{}
\n
{}
    感谢您的使用,如果您使用中遇到问题和意见可反馈给我。
    联系邮箱：{}
"""
HELP_MSG_HEADERS = [u'技术', u'非常感谢']
ABOUT_MSG = u"""
{}  版本：{}
作者：{}
"""
ABOUT_MSG_OTHER = u"""
{}
    邮箱：{}
\n
{}
    写的玩的,欢迎各位大佬多多指点!
"""
ABOUT_MSG_OTHER_HEADERS = [u'联系', u'说明']
FILE_MSG_OTHER_HEADERS = [u"截图保存目录：", u"最大保存额度：", u"未生效新路径："]

# 路径
CUR_DIR = os.getcwd()

# Mapping
MAP_PATH = r"{}\tmp_{}.png"
# save
SAVE_PATH = r"{}\cap_{}.png"

# 配置文件路径M
MAX_YAML_SIZE = 1 * 1024 * 1024
SETTING_PATH = os.path.dirname(CUR_DIR)
MAX_DIR_SIZE = 1

# 默认值
SAVE_DIR = os.path.join(CUR_DIR, "capture_imgs")
MAP_DIR = os.path.join(SAVE_DIR, "temp")
START_TIME_DELTA = 1 * 60 * 60


def read_yaml(path):
    if os.path.exists(path) and os.path.isabs(path):
        if os.path.getsize(path) > MAX_YAML_SIZE:
            return {}
        try:
            with open(path, encoding='utf-8') as f:
                content = f.read()
                config = yaml.safe_load(content) if content else {}
            return config
        except Exception as e:
            return {}
    return {}


def write_yaml(key_vals):
    path = os.path.join(os.path.dirname(CUR_DIR), "setting\settings.yaml")
    config = read_yaml(path)
    for key in key_vals.keys():
        config[key] = key_vals[key]
    with open(path, mode="w", encoding='utf-8') as f:
        yaml.dump(config, f, allow_unicode=True)


def get_config_from_yaml():
    path = os.path.join(os.path.dirname(CUR_DIR), "setting\settings.yaml")
    config = read_yaml(path)
    global MAX_DIR_SIZE
    MAX_DIR_SIZE = Decimal(str(config.get("MAX_DIR_SIZE", 1)))
    global SAVE_DIR
    SAVE_DIR = config.get("SAVE_DIR", SAVE_DIR)
    global MAP_DIR
    MAP_DIR = config.get("MAP_DIR", MAP_DIR)


def recard_pid(path):
    config = {"SHOT_PID": os.getpid(), "START_TIME": time.time(), "IS_RESTART": False}
    with open(path, mode="w", encoding='utf-8') as f:
        yaml.dump(config, f, allow_unicode=True)


def restart_recard_pid():
    config = {"IS_RESTART": True}
    path = os.path.join(os.path.dirname(CUR_DIR), "setting\pid.lock")
    with open(path, mode="w", encoding='utf-8') as f:
        yaml.dump(config, f, allow_unicode=True)


def check_pid():
    path = os.path.join(os.path.dirname(CUR_DIR), "setting\pid.lock")
    config = read_yaml(path)
    if config.get("IS_RESTART") or config.get("SHOT_PID") is None:
        recard_pid(path)
        return True
    elif config.get("SHOT_PID") and config.get("START_TIME"):
        delta = config.get("START_TIME") - time.time()
        if abs(delta) > START_TIME_DELTA:
            recard_pid(path)
            return True
    return False


def check_path():
    if not os.path.exists(SAVE_DIR):
        os.mkdir(SAVE_DIR)
    if not os.path.exists(MAP_DIR):
        os.mkdir(MAP_DIR)


def get_map_path():
    lt = time.localtime()  # UTC格式当前时区时间
    st = time.strftime("%Y%m%d%H%M%S", lt)
    return MAP_PATH.format(MAP_DIR, st)


def get_save_path():
    lt = time.localtime()  # UTC格式当前时区时间
    st = time.strftime("%Y%m%d%H%M%S", lt)
    return SAVE_PATH.format(SAVE_DIR, st)


def get_msg(header):
    num = len(header)
    if num < 60:
        header = header + '-' * (60 - num * 2)
    return header


def get_file_size(path):
    size = 0
    for dir, dirs, files in os.walk(path):
        for file in files:
            if file.endswith("png"):
                size += os.path.getsize(os.path.join(dir, file))
    return Decimal(str(size / 1024 / 1024))


def help_tab(frame2):
    message_version = tk.Message(frame2, text=HELP_MSG.format(get_msg(HELP_MSG_HEADERS[0]), GIT_PATH,
                                                              get_msg(HELP_MSG_HEADERS[1]), EMAIL),
                                 font=('黑体', 10),
                                 relief='flat', bg='white', width=420, anchor='w')
    message_version.grid(column=0, row=0)


def about_tab(frame2, pic_3):
    label_img = tk.Label(frame2, image=pic_3, anchor='e', bg='white')
    label_img.grid(column=0, ipadx=45, row=0)
    message_version = tk.Label(frame2, text=ABOUT_MSG.format(NAME, VERSION, EDITOR, ), font=('黑体', 10),
                               bg='white', anchor='e')
    message_version.grid(column=1, columnspan=2, ipadx=0, ipady=31, row=0)
    message_other = tk.Label(frame2, text=ABOUT_MSG_OTHER.format(get_msg(ABOUT_MSG_OTHER_HEADERS[0]), EMAIL,
                                                                 get_msg(ABOUT_MSG_OTHER_HEADERS[1])),
                             font=('黑体', 10),
                             bg='white', anchor='w')
    message_other.grid(column=0, columnspan=2, ipadx=0, row=1)


def select_dir(new_config, lb_path_new, et_path_new, frame2):
    dir_path = askdirectory(parent=frame2, initialdir=SAVE_DIR)
    if dir_path and dir_path != SAVE_DIR:
        new_config["SAVE_DIR"] = dir_path
        new_config["MAP_DIR"] = os.path.join(dir_path, "temp")
        lb_path_new["text"] = FILE_MSG_OTHER_HEADERS[2]
        et_path_new.insert('0', dir_path)
        lb_path_new.grid(row=3, column=0)
        et_path_new.grid(row=3, column=1)


def open_dir(frame2):
    if os.path.exists(SAVE_DIR):
        os.startfile(SAVE_DIR)

def restart(window, new_config):
    """确认配置项后重启应用"""
    if new_config:
        write_yaml(new_config)
        restart_recard_pid()
        window.destroy()
        gui_main()


def update_config_by_key(tmp, new_config, key):
    """根据待更新的key和输入值更新配置项"""
    if tmp:
        max_dir_size = tmp[-1].get()
        new_config[key] = max_dir_size


def notice(header, notice, func, *args):
    # res = messagebox.showinfo("温馨提示", u"重新选择目录将不会")   # 弹窗只有确定按钮
    if messagebox.askyesno(header, notice):
        func(*args)


def judge(header, notice, func, *args):
    """弹窗确认，OK就执行func"""
    if messagebox.askquestion(header, notice):
        func(*args)


def file_tab(window, frame2, pic_6, pic_7):
    """选项-文件配置"""
    new_config = {}
    # 截图文件保存路径
    lb_file = tk.Label(frame2, text=FILE_MSG_OTHER_HEADERS[0], font=('黑体', 10),
                       bg="white")
    lb_file.grid(column=0, row=2)
    et_file = tk.Entry(frame2, width=35, relief="groove", bd=2, bg="white")
    et_file.insert('0', SAVE_DIR)
    et_file.grid(row=2, column=1)
    et_file["state"] = 'disabled'

    lb_path_new = tk.Label(frame2, font=('黑体', 10), bg='white', anchor='w')
    et_path_new = tk.Entry(frame2, width=35, relief="groove", bd=2, bg="white")
    header1, notice1 = "温馨提示", "注意：重新选择目录将不会删除旧数据，也不会迁移旧数据！\r\n是否继续？"
    select_btn = tk.Button(frame2, text="选取目录", image=pic_6,
                           command=lambda: notice(header1, notice1, select_dir, new_config, lb_path_new, et_path_new, frame2),
                           bg="white", anchor='w', relief="flat")
    select_btn.grid(row=2, column=2)

    select_btn = tk.Button(frame2, text="查看目录", image=pic_7,
                           command=lambda : open_dir(frame2), bg="white", anchor='w', relief="flat")
    select_btn.grid(row=2, column=3)

    lb_file_size = tk.Label(frame2, text=FILE_MSG_OTHER_HEADERS[1], font=('黑体', 10),
                            bg="white")
    lb_file_size.grid(column=0, row=4)

    var = tk.IntVar()
    var.set(MAX_DIR_SIZE)
    tmp = []
    # 注意command参数使用lambda可以带上参数，否则只使用函数名，没办法带关联参数。
    # 且按钮自身要在comman中使用自身， 简单的方法是将按钮对象加入列表，之后将列表传入lambda函数里面使用
    et_file_size = tk.Spinbox(frame2, from_=1, to=20, width=10, textvariable=var, relief="groove", bd=2, bg="white",
                              command=lambda: update_config_by_key(tmp, new_config, "MAX_DIR_SIZE"))
    tmp.append(et_file_size)
    et_file_size.grid(row=4, column=1)
    header2, notice2 = "确认", "是否确认？确认之后将立刻更新配置并重启应用。"
    ok_btn = tk.Button(frame2, text="确定", command=lambda: judge(header2, notice2, restart, window, new_config),
                       bg="white",anchor='c', relief="groove", font=('黑体', 10))
    ok_btn.grid(row=10, column=3)


def distributor(window, winNew, frame1, frame2, type, pic_2, pic_3, pic_4, pic_5, pic_6, pic_7):
    """根据tab页类型展示页面"""
    frame1.destroy()
    frame2.destroy()
    frame1, frame2 = build_new_frame(window, winNew, pic_2, pic_3, pic_4, pic_5, pic_6, pic_7)
    if type == "help":
        help_tab(frame2)
    elif type == "about":
        about_tab(frame2, pic_3)
    elif type == "file":
        file_tab(window, frame2, pic_6, pic_7)


def build_new_win(window):
    """创建子窗口-选项"""
    winNew = tk.Toplevel(window)
    winNew.geometry('600x400')
    winNew.title(u'ScreenShotTool-选项')
    winNew.iconbitmap(r"..\statics\favicon.ico")
    winNew.configure(bg='white')

    return winNew


def build_new_frame(window, winNew, pic_2, pic_3, pic_4, pic_5, pic_6, pic_7):
    """子窗口-选项 左边frame1展示tab页名称，右边frame2展示内容"""
    frame1 = tk.Frame(winNew, relief="sunken", bg='white')
    frame1.place(relx=0)

    frame2 = tk.Frame(winNew, relief="groove", bg='white')
    frame2.place(relx=0.20, rely=0.05)
    btn1 = tk.Button(frame1, text='关于', image=pic_2,
                     command=lambda: distributor(window, winNew, frame1, frame2, 'about', pic_2, pic_3, pic_4, pic_5,
                                                 pic_6,
                                                 pic_7),
                     relief='flat', bg='white', width=80, anchor='w', font=('黑体', 12), compound='left',
                     activeforeground="red")
    btn1.grid(column=0, row=1)
    btn2 = tk.Button(frame1, text='支持', image=pic_4,
                     command=lambda: distributor(window, winNew, frame1, frame2, 'help', pic_2, pic_3, pic_4, pic_5,
                                                 pic_6,
                                                 pic_7),
                     bg='white', relief='flat', width=80, anchor='w', font=('黑体', 12), compound='left',
                     activeforeground="red")
    btn2.grid(column=0, row=3)

    btn3 = tk.Button(frame1, text='文件', image=pic_5,
                     command=lambda: distributor(window, winNew, frame1, frame2, 'file', pic_2, pic_3, pic_4, pic_5,
                                                 pic_6,
                                                 pic_7),
                     bg='white', relief='flat', width=80, anchor='w', font=('黑体', 12), compound='left',
                     activeforeground="red")
    btn3.grid(column=0, row=2)

    return frame1, frame2


def new_wind(window):
    """选项按钮子窗口展示， 默认展示关于tab页"""
    pic_2 = tk.PhotoImage(file=r"..\statics\about.png")  # 子窗口图片路径必须全局变量,不然图片无法展示
    pic_3 = tk.PhotoImage(file=r"..\statics\ScreenShot.png")
    pic_4 = tk.PhotoImage(file=r"..\statics\help.png")
    pic_5 = tk.PhotoImage(file=r"..\statics\fileSetting.png")
    pic_6 = tk.PhotoImage(file=r"..\statics\select_dir.png")
    pic_7 = tk.PhotoImage(file=r"..\statics\view_dir.png")
    winNew = build_new_win(window)
    frame1, frame2 = build_new_frame(window, winNew, pic_2, pic_3, pic_4, pic_5, pic_6, pic_7)
    about_tab(frame2, pic_3)


class Box:
    """截图时图片坐标工具类"""

    def __init__(self):
        self.start_x = None
        self.start_y = None
        self.end_x = None
        self.end_y = None

    def is_none(self):
        return self.start_x is None or self.end_x is None

    def set_start(self, x, y):
        self.start_x = x
        self.start_y = y

    def set_end(self, x, y):
        self.end_x = x
        self.end_y = y

    def box(self):
        lt_x = min(self.start_x, self.end_x)
        lt_y = min(self.start_y, self.end_y)
        rb_x = max(self.start_x, self.end_x)
        rb_y = max(self.start_y, self.end_y)
        return lt_x, lt_y, rb_x, rb_y

    def center(self):
        center_x = (self.start_x + self.end_x) / 2
        center_y = (self.start_y + self.end_y) / 2
        return center_x, center_y


class SelectionArea:
    """获取截图区域工具类"""

    def __init__(self, canvas: tk.Canvas):
        self.canvas = canvas
        self.area_box = Box()

    def empty(self):
        return self.area_box.is_none()

    def set_start_point(self, x, y):
        self.canvas.delete('area', 'lt_txt', 'rb_txt')
        self.area_box.set_start(x, y)
        # 开始坐标文字
        self.canvas.create_text(
            x, y - 10, text=f'({x}, {y})', fill='red', tag='lt_txt')

    def update_end_point(self, x, y):
        self.area_box.set_end(x, y)
        self.canvas.delete('area', 'rb_txt')
        box_area = self.area_box.box()
        # 选择区域
        self.canvas.create_rectangle(
            *box_area, fill='black', outline='blue', width=5, tags="area")
        self.canvas.create_text(
            x, y + 10, text=f'({x}, {y})', fill='red', tag='rb_txt')


def get_real_resolution():
    """获取真实的分辨率"""
    hDC = win32gui.GetDC(0)
    # 横向分辨率
    w = win32print.GetDeviceCaps(hDC, win32con.DESKTOPHORZRES)
    # 纵向分辨率
    h = win32print.GetDeviceCaps(hDC, win32con.DESKTOPVERTRES)
    return w, h


def get_screen_size():
    """获取缩放后的分辨率"""
    w = GetSystemMetrics(0)
    h = GetSystemMetrics(1)
    return w, h


class ScreenShot():
    """截图功能实现类"""

    def __init__(self, window, lb_file_size, lb_file, cap_size, temp_size):
        self.raw_height = 0
        self.raw_width = 0
        self.window = window
        self.lb_file_size = lb_file_size
        self.lb_file = lb_file
        self.cap_size = cap_size
        self.temp_size = temp_size
        self.x = tk.IntVar(value=0)
        self.y = tk.IntVar(value=0)
        self.width = self.window.winfo_screenwidth()
        self.height = self.window.winfo_screenheight()
        self.is_selecting = False  # 是否选择截图区域
        self.num = 0  # 显示截图配置项
        self.is_map = 0  # 是否贴图
        self.is_tmp = 0  # 是否临时文件
        self.is_zoom = 0  # 是否缩放
        self.pic_close = tk.PhotoImage(file=r"..\statics\close.png")
        self.pic_save = tk.PhotoImage(file=r"..\statics\save.png")
        self.pic_map = tk.PhotoImage(file=r"..\statics\map.png")
        self.top = tk.Toplevel(self.window, width=self.width, height=self.height)
        self.top.overrideredirect(True)
        self.top.wm_attributes("-alpha", 0.7)  # 透明度(0.0~1.0)
        # top.wm_attributes("-toolwindow", True)  # 置为工具窗口(没有最大最小按钮)
        # top.wm_attributes("-topmost", True)  # 永远处于顶层
        self.cv = tk.Canvas(self.top, bg='white', width=self.width, height=self.height)
        self.cv.pack()
        self.top.bind('<KeyPress-Escape>', self.exit)  # 绑定按 Enter 确认, Esc 退出
        self.top.bind('<KeyPress-Return>', self.confirm_screen_shot)
        # 鼠标按下
        self.top.bind('<Button-1>', self.select_start)
        # 鼠标释放
        self.top.bind('<ButtonRelease-1>', self.select_done)
        # 鼠标按下移动
        self.top.bind('<Motion>', self.change_selection_area)
        self.frame_tool = tk.Frame(self.top, relief="groove")
        self.area = SelectionArea(self.cv)

    def del_img(self):
        """删除图片（如退出时删除临时文件）"""
        if self.is_tmp:
            # 主页更新文件数字
            cur_size = Decimal(str(os.path.getsize(self.tmp_path) / 1024 / 1024))
            os.remove(self.tmp_path)
            self.map_top.destroy()
            self.is_tmp = 0
            self.tmp_path = None
            new_cap_size, new_temp_size = self.cap_size, self.temp_size - cur_size
            self.update_file_size(new_cap_size, new_temp_size)

    def exit(self, event):
        self.top.destroy()
        self.del_img()

    def tmp_exit(self):
        """贴图页面退出关闭页面并删除临时文件"""
        self.map_top.destroy()
        self.del_img()

    def clear(self):
        self.cv.delete('area', 'lt_txt', 'rb_txt')
        self.top.attributes('-alpha', 0)

    def get_scale_rate(self):
        real_resolution = get_real_resolution()
        screen_size = get_screen_size()

        # Windows 设置的屏幕缩放率
        # ImageGrab 的参数是基于显示分辨率的坐标，而 tkinter 获取到的是基于缩放后的分辨率的坐标
        screen_scale_rate = round(real_resolution[0] / screen_size[0], 2)

        return screen_scale_rate

    def capture_image(self):
        if self.area.empty():
            return None, None
        else:
            screen_scale_rate = self.get_scale_rate()
            box_area = [x * screen_scale_rate for x in self.area.area_box.box()]
            self.clear()
            img = ImageGrab.grab(box_area)
            img.save(self.tmp_path, u"PNG")
            # 主页更新文件数字
            cur_size = Decimal(str(os.path.getsize(self.tmp_path) / 1024 / 1024))
            new_cap_size, new_temp_size = self.cap_size, self.temp_size + cur_size
            self.update_file_size(new_cap_size, new_temp_size)
            return img, box_area

    def confirm_screen_shot(self, event):
        """截图时直接按enter截图"""
        self.tmp_path = get_save_path()
        self.capture_image()
        # 主页更新文件数字
        cur_size = Decimal(str(os.path.getsize(self.tmp_path) / 1024 / 1024))
        new_cap_size, new_temp_size = self.cap_size + cur_size, self.temp_size
        self.update_file_size(new_cap_size, new_temp_size)
        self.top.destroy()

    def save(self, event):
        """截图直接保存图片"""
        if not self.area.empty():
            screen_scale_rate = self.get_scale_rate()
            box_area = [x * screen_scale_rate for x in self.area.area_box.box()]
            self.clear()
            img = ImageGrab.grab(box_area)
            self.save_path = get_save_path()
            img.save(self.save_path, u"PNG")
            # 主页更新文件数字
            cur_size = Decimal(str(os.path.getsize(self.save_path) / 1024 / 1024))
            new_cap_size, new_temp_size = self.cap_size + cur_size, self.temp_size
            self.update_file_size(new_cap_size, new_temp_size)

        self.top.destroy()

    def save_map_img(self):
        """鼠标右键保存图片"""
        if self.is_tmp:
            # 判断临时文件是否超额
            img = Image.open(self.tmp_path)
            self.save_path = get_save_path()
            img.save(self.save_path, u"PNG")
            # 主页更新文件数字
            cur_size = Decimal(str(os.path.getsize(self.tmp_path) / 1024 / 1024))
            new_cap_size, new_temp_size = self.cap_size + cur_size, self.temp_size
            self.update_file_size(new_cap_size, new_temp_size)

    def select_start(self, event):
        """截图开始更新首个坐标点"""
        self.is_selecting = True
        self.x = tk.IntVar(value=event.x)
        self.y = tk.IntVar(value=event.y)
        self.area.set_start_point(event.x, event.y)

    def change_selection_area(self, event):
        """截图时鼠标按动更新坐标"""
        if self.is_selecting:
            self.area.update_end_point(event.x, event.y)

    def select_done(self, event):
        """截图时鼠标退出"""
        self.is_selecting = False
        self.num += 1
        if not self.is_tmp:
            self.tmp_path = get_map_path()
        self.set_handler_tool(event.x, event.y)

    def close(self):
        """截图页面退出，不关闭主页面"""
        self.top.destroy()

    def zoom_img(self, event):
        """贴图时图片缩小放大展示"""
        if self.is_tmp:
            if self.raw_width == event.width and self.raw_height == event.height:
                return
            self.raw_width, self.raw_height = event.width, event.height
            # 先减去旧的临时文件
            pre_temp_size = Decimal(str(os.path.getsize(self.tmp_path) / 1024 / 1024))
            img = Image.open(self.tmp_path)
            img = img.resize((self.raw_width, self.raw_height), Image.ANTIALIAS)
            img.save(self.tmp_path, u"PNG")
            self.img_png = tk.PhotoImage(file=self.tmp_path)
            self.cv_img(self.raw_width, self.raw_height, self.img_png)
            # 主页更新文件数字
            cur_size = Decimal(str(os.path.getsize(self.tmp_path) / 1024 / 1024))
            new_cap_size, new_temp_size = self.cap_size, self.temp_size + cur_size - pre_temp_size
            self.update_file_size(new_cap_size, new_temp_size)

    def map_img(self, event):
        """贴图"""
        _, box_area = self.capture_image()
        lt_x, lt_y, rb_x, rb_y = box_area
        # 展示页面
        self.show_img(lt_x, lt_y, rb_x, rb_y, self.tmp_path)

    def show_menu(self, event):
        """贴图页面鼠标右键时选项"""
        menu = tk.Menu(self.frame_tool, tearoff=False)
        menu.add_command(label="保存", command=self.save_map_img)
        menu.add_command(label="关闭", command=self.tmp_exit)
        menu.post(event.x_root, event.y_root)

    def show_img(self, lt_x, lt_y, rb_x, rb_y, img_path):
        self.map_top = tk.Toplevel(self.window)
        self.map_top.protocol("WM_DELETE_WINDOW", self.tmp_exit)
        self.map_top.bind("<Configure>", self.zoom_img)
        # <Button-3>：鼠标右键事件
        self.map_top.bind("<Button-3>", self.show_menu)
        self.map_top.wm_attributes("-topmost", True)
        self.map_top.iconbitmap(r"..\statics\favicon.ico")
        self.img_png = tk.PhotoImage(file=img_path)
        width = math.fabs(rb_x - lt_x)
        height = math.fabs(rb_y - lt_y)
        self.raw_width, self.raw_height = width, height
        self.cv_img(width, height, self.img_png)

    def cv_img(self, width, height, img_png):
        # 根据桌面上鼠标移动坐标利用canvas绘制图片画布
        if not self.is_tmp:
            self.canvas = tk.Canvas(self.map_top, width=width, height=height)
        if self.is_tmp and self.img_id:
            self.canvas.delete(self.img_id)
        self.canvas.width = width
        self.canvas.height = height
        self.canvas.imageList = []
        self.canvas.pack(expand="YES", fill="both")
        self.img_id = self.canvas.create_image(0, 0, anchor="nw", image=img_png)
        self.canvas.imageList.append(img_png)
        self.is_tmp = 1

    def set_handler_tool(self, rb_x, rb_y):
        """展示截图工具栏"""
        if self.num:
            if rb_x < self.x.get():
                rb_x = self.x.get()
            if rb_y < self.y.get():
                rb_y = self.y.get()
            self.frame_tool.place(x=rb_x - 75, y=rb_y + 20)
            btn1 = tk.Button(self.frame_tool, text='取消', image=self.pic_close, bg="black",
                             command=self.close, relief='groove', width=20, anchor='center')
            btn1.grid(column=0, row=0)
            btn2 = tk.Button(self.frame_tool, text='保存', image=self.pic_save, bg="black",
                             relief='groove', width=20, anchor='center')
            btn2.grid(column=2, row=0)
            btn2.bind("<Button-1>", self.save)
            btn3 = tk.Button(self.frame_tool, text='贴图', image=self.pic_map, bg="black",
                             relief='groove', width=20, anchor='center')
            btn3.grid(column=1, row=0)
            btn3.bind("<Button-1>", self.map_img)
            self.num = 0

    def update_file_size(self, new_cap_size, new_temp_size):
        """截图后图片大小改变更新和桌面提示"""
        if new_cap_size != self.cap_size or new_temp_size != self.temp_size:
            self.lb_file_size['text'] = u'截图文件(最大{}MB)：{} MB，临时文件(最大{}MB)：{} MB'.format(MAX_DIR_SIZE,
                                                                                        new_cap_size.quantize(
                                                                                            Decimal("0.000"),
                                                                                            ROUND_HALF_UP),
                                                                                        MAX_DIR_SIZE,
                                                                                        new_temp_size.quantize(
                                                                                            Decimal("0.000"),
                                                                                            ROUND_HALF_UP))
        if new_cap_size > MAX_DIR_SIZE or new_temp_size > MAX_DIR_SIZE:
            self.lb_file_size['fg'] = 'red'
            if self.lb_file:
                self.lb_file[-1]['text'] = "(请清理文件！)"
                self.lb_file[-1]['state'] = 'disabled'
                self.lb_file[-1]['compound'] = 'top'
                self.lb_file[-1]['height'] = 118
        self.cap_size, self.temp_size = new_cap_size, new_temp_size


def check_file_size(total_size):
    if total_size > MAX_DIR_SIZE:
        return True
    return False


def capture(window, lb_file_size, lb_file, cap_size, temp_size):
    ScreenShot(window, lb_file_size, lb_file, cap_size, temp_size)


def tool(window, lb_file_size, pic_shot, pic_camera, pic_draw, pic_edit):
    """截图、摄像头、画板和编辑按钮展示"""
    cap_size = get_file_size(r"..\capture")
    temp_size = get_file_size(r"..\temp")
    lb_file_size['text'] = u'截图文件(最大{}MB)：{} MB，临时文件(最大{}MB)：{} MB'.format(MAX_DIR_SIZE,
                                                                           cap_size.quantize(Decimal("0.000"),
                                                                                             ROUND_HALF_UP),
                                                                           MAX_DIR_SIZE,
                                                                           temp_size.quantize(Decimal("0.000"),
                                                                                              ROUND_HALF_UP))
    lb_file = []
    btn_shot = tk.Button(window, text='截图', image=pic_shot, relief='groove', bg="white", width=110, height=120,
                         anchor='center', font=('黑体', 10),
                         command=lambda: capture(window, lb_file_size, lb_file, cap_size, temp_size))

    btn_camera = tk.Button(window, text='(待开发)', image=pic_camera, relief='groove', bg="white", width=110, height=118,
                           anchor='center', font=('黑体', 10), compound='top')
    btn_draw = tk.Button(window, text='(待开发)', image=pic_draw, relief='groove', bg="white", width=110, height=118,
                         anchor='center', font=('黑体', 10), compound='top')
    btn_edit = tk.Button(window, text='(待开发)', image=pic_edit, relief='groove', bg="white", width=110, height=118,
                         anchor='center', font=('黑体', 10), compound='top')
    if check_file_size(cap_size) or check_file_size(temp_size):
        btn_shot['state'] = 'disabled'
        btn_shot['text'] = "(请清理文件！)"
        btn_shot['compound'] = 'top'
        btn_shot['height'] = 118
        lb_file_size['fg'] = 'red'
    else:
        lb_file_size['fg'] = 'blue'

    lb_file_size.place(x=50, y=33)
    btn_edit.place(x=350, y=65)
    btn_edit["state"] = 'disabled'
    btn_draw.place(x=235, y=65)
    btn_draw["state"] = 'disabled'
    btn_camera.place(x=125, y=65)
    btn_camera["state"] = 'disabled'
    btn_shot.place(x=15, y=65)
    lb_file.append(btn_shot)


def window_exit(window):
    restart_recard_pid()
    window.destroy()


def gui_main():
    # 读取pid文件，存在值，不再执行
    if not check_pid():
        return
    # 读取配置
    get_config_from_yaml()

    # 检查目录
    check_path()

    # 窗口初始化
    window = tk.Tk()

    # 窗口名称
    window.title("ScreenShotTool")
    # 设置窗口图标ico
    window.iconbitmap(r"..\statics\favicon.ico")
    # 设置窗口大小
    window.geometry('480x200')
    # 背景
    window.configure(bg='white')
    # 设置标签  text： 文字  bg:背景  fg:字体颜色  font:字体  width:字符宽  height：字符高
    lb_tool = tk.Label(window, text='ScreenShotTool', bg='white', font=('Arial', 14), width=20, height=2, anchor='w')
    lb_ver = tk.Label(window, text=u'当前版本：{}'.format(VERSION), bg='white', fg='blue', cursor="hand2",
                      font=('宋体', 10, "bold", "underline"), width=25, height=2, anchor='e')

    lb_file_size = tk.Label(window, bg='white', font=('宋体', 10), width=60, height=2, anchor='e')

    pic_1 = tk.PhotoImage(file=r"..\statics\select.png")
    btn_2 = tk.Button(window, text='选项', image=pic_1, command=lambda: new_wind(window), relief='flat', bg="white",
                      width=60, font=('黑体', 12), compound='left')
    btn_2.place(x=410, y=0)
    lb_ver.place(x=205, y=5)
    lb_tool.place(x=0, y=0)

    pic_shot = tk.PhotoImage(file=r"..\statics\shot.png")
    pic_camera = tk.PhotoImage(file=r"..\statics\camera.png")
    pic_draw = tk.PhotoImage(file=r"..\statics\draw.png")
    pic_edit = tk.PhotoImage(file=r"..\statics\edit.png")
    tool(window, lb_file_size, pic_shot, pic_camera, pic_draw, pic_edit)
    # ESC
    window.bind('<KeyPress-Escape>', window_exit)
    # 关闭x
    window.protocol('WM_DELETE_WINDOW', lambda : window_exit(window))
    window.mainloop()


if __name__ == '__main__':
    gui_main()
